// Copyright 2000-2022 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.

package com.zzx.component;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ToolWindow;
import com.zzx.settings.AppSettingsState;
import com.zzx.utils.BaseUtil;
import com.zzx.utils.HttpUtil;

import javax.swing.*;
import javax.swing.text.DefaultCaret;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.event.*;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

public class MyToolWindow {
  private static final Logger log =
          Logger.getInstance(MyToolWindow.class);

  private JPanel myToolWindowContent;
  private JLabel repository;
  private JButton refresh;
  private JTree treeList;
  private JProgressBar progressBar;
  private JTextArea textArea;
  private AppSettingsState settings;
  private AtomicBoolean flag;
  private Object o = new Object();
  private AtomicLong atomicLong;
  DefaultMutableTreeNode root = new DefaultMutableTreeNode("本地仓库");
  DefaultTreeModel dt = new DefaultTreeModel(root);
  JPopupMenu popupMenu;
  JMenuItem menuItem;

  ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);


  public MyToolWindow(ToolWindow toolWindow) {
    this.atomicLong = new AtomicLong(0);
    this.flag = new AtomicBoolean(false);
    this.settings = AppSettingsState.getInstance();
    treeList.setModel(dt);
    repository.setText(" 本地仓库地址："+settings.repository);
    popupMenu = new JPopupMenu();
    menuItem = new JMenuItem("上传");
    popupMenu.add(menuItem);
    textArea.setRows(0);
    DefaultCaret caret = (DefaultCaret) textArea.getCaret();
    caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
    progressBar.setVisible(false);
    progressBar.setMinimum(0);
    progressBar.setStringPainted(true);
    refresh.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        repository.setText("本地仓库地址："+settings.repository);
        File file = new File(settings.repository);
        if(!file.exists()){
          Messages.showMessageDialog("本地仓库路径不存在，请在settings->tools->Maven私服上传 中进行设置","错误信息",Messages.getErrorIcon());
          return;
        }
        fixedThreadPool.submit(new Runnable() {
          @Override
          public void run() {
            refresh();
          }
        });
      }
    });
    menuItem.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        if(StringUtil.isEmpty(settings.nexus)||StringUtil.isEmpty(settings.repository)||StringUtil.isEmpty(settings.username)||StringUtil.isEmpty(settings.password)){
          Messages.showMessageDialog("未初始化环境，请在settings->tools->Maven私服上传 中进行设置","错误信息",Messages.getErrorIcon());
        }
        synchronized (o){
          if(flag.get()){
            Messages.showMessageDialog("上传中请稍后再试","提示信息",Messages.getInformationIcon());
            return;
          }
        }
        progressBar.setValue(0);
        atomicLong.set(0);
        StringBuilder tempSpot = new StringBuilder("");
        StringBuilder tempPath = new StringBuilder(new File(settings.repository).getPath());
        if(!settings.nexus.endsWith("/")){
          tempSpot.append(settings.nexus+"/");
        }else {
          tempSpot.append(settings.nexus);
        }
        tempPath.append(File.separator);
        TreePath path = treeList.getSelectionPath();
        for(int counter = 1, maxCounter = path.getPathCount();counter < maxCounter;
            counter++) {
          if(counter > 1){
            tempSpot.append("/");
            tempPath.append(File.separator);
          }
          tempPath.append(path.getPathComponent(counter));
          tempSpot.append(path.getPathComponent(counter));
        }
        File file = new File(tempPath.toString());
        textArea.setRows(5);
        textArea.setText("上传中。。。。。。\n");
        progressBar.setVisible(true);
        flag.set(true);
        if(file.isDirectory()){
          List<File> fileLists = getAllFile(file.getAbsolutePath(),false);
          progressBar.setMaximum(fileLists.size());
          for(int i = 0 ; i< fileLists.size();i++){
            int finalI = i;
            fixedThreadPool.submit(new Runnable() {
              @Override
              public void run() {
                File uploadFile = fileLists.get(finalI);
                if(!BaseUtil.isUpload(uploadFile.getName())){
                  long num = atomicLong.incrementAndGet();
                  progressBar.setValue((int) num);
                  if(num>=progressBar.getMaximum()){
                    textArea.append("上传完成\n");
                    progressBar.setVisible(false);
                    flag.set(false);
                  }
                  return;
                }
                log.info(uploadFile.getAbsolutePath());
                String s = tempSpot + (uploadFile.getAbsolutePath().replace(tempPath.toString(), "").replace("\\", "/"));
                textArea.append("开始上传:"+uploadFile.getAbsolutePath()+"\n");
                HttpUtil.put(s,settings.username,settings.password,new File(fileLists.get(finalI).getAbsolutePath()),textArea,progressBar,atomicLong,flag);
              }
            });
          }
        }else {
          progressBar.setMaximum(1);
          fixedThreadPool.submit(new Runnable() {
            @Override
            public void run() {
              textArea.append("开始上传:"+tempPath+"\n");
              HttpUtil.put(tempSpot.toString(),settings.username,settings.password,new File(tempPath.toString()),textArea,progressBar,atomicLong,flag);
            }
          });
        }

      }
    });
    treeList.addMouseListener(new MouseAdapter() {
      @Override
      public void mousePressed(MouseEvent e) {
        TreePath path = treeList.getPathForLocation(e.getX(),e.getY());
        if(path==null){
          return;
        }
        treeList.setSelectionPath(path);
        if(e.getButton()==MouseEvent.BUTTON3){
          popupMenu.show(treeList,e.getX(),e.getY());
        }
      }
    });
  }
  public void refresh(){
    long start = System.currentTimeMillis();
    root.removeAllChildren();
    File file = new File(settings.repository);
    File[] files = file.listFiles();
    for(int i = 0 ; i<files.length ; i++){
      File child = files[i];
      DefaultMutableTreeNode node = new DefaultMutableTreeNode(child.getName());
      if(child.isDirectory()){
        add(child,node);
        root.add(node);
      }else {
        if(BaseUtil.isUpload(child.getName())){
          root.add(node);
        }else {
          log.info(child.getAbsolutePath());
        }
      }
    }
    log.info("loading time:"+(System.currentTimeMillis()-start));
  }
  public void add(File file,DefaultMutableTreeNode root){
    File[] files = file.listFiles();
    for(int i = 0 ; i<files.length ; i++){
      File child = files[i];
      DefaultMutableTreeNode node = new DefaultMutableTreeNode(child.getName());
      if(child.isDirectory()){
        add(child,node);
        root.add(node);
      }else {
        if(BaseUtil.isUpload(child.getName())){
          root.add(node);
        }
      }
    }
  }
  public JPanel getContent() {
    return myToolWindowContent;
  }

  private void createUIComponents() {
    // TODO: place custom component creation code here
  }
  public static List<File> getAllFile(String directoryPath,boolean isAddDirectory) {
    List<File> list = new ArrayList<>();
    File baseFile = new File(directoryPath);
    if (baseFile.isFile() || !baseFile.exists()) {
      return list;
    }
    File[] files = baseFile.listFiles();
    for (File file : files) {
      if (file.isDirectory()) {
        if(isAddDirectory){
          list.add(file);
        }
        list.addAll(getAllFile(file.getAbsolutePath(),isAddDirectory));
      } else {
        list.add(file);
      }
    }
    return list;
  }
}
